package org.dromara.patrol.dubbo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.dromara.common.core.enums.NoticeMessageType;
import org.dromara.common.core.enums.patrol.ExpiredStatus;
import org.dromara.common.core.enums.patrol.MainTaskType;
import org.dromara.common.core.enums.patrol.RepeatType;
import org.dromara.common.core.enums.patrol.TaskFinishStatus;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.patrol.api.RemotePatrolSubtaskCommonService;
import org.dromara.patrol.api.domain.bo.RemotePatrolSubtaskBo;
import org.dromara.patrol.api.domain.vo.RemotePatrolSubtaskVo;
import org.dromara.patrol.api.domain.vo.RemotePatrolTaskVo;
import org.dromara.patrol.domain.PatrolSubtaskCommon;
import org.dromara.patrol.domain.model.PatrolExecutors;
import org.dromara.patrol.domain.vo.PatrolSubtaskCommonVo;
import org.dromara.patrol.service.IPatrolSubtaskCommonService;
import org.dromara.system.api.RemoteMessageService;
import org.dromara.system.api.RemoteStoreService;
import org.dromara.system.api.domain.bo.RemoteMessageBo;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static cn.dev33.satoken.SaManager.log;

@RequiredArgsConstructor
@Service
@DubboService
public class RemotePatrolSubtaskCommonServiceImpl implements RemotePatrolSubtaskCommonService {

    private final IPatrolSubtaskCommonService patrolSubtaskService;

    @DubboReference
    private RemoteStoreService remoteStoreService;

    @DubboReference
    private RemoteMessageService remoteMessageService;

    @Override
    public List<RemotePatrolSubtaskVo> createNonMainPatrolSubtask(RemotePatrolSubtaskBo remotePatrolSubtaskBo) {
        // 判断是否已经生成巡检子任务
        String dateStr = remotePatrolSubtaskBo.getDateStr();
        Long hasCount = patrolSubtaskService.countByRemoteBo(remotePatrolSubtaskBo);
        if (hasCount > 0L) {
            // 查询是否已生成任务，变更未完成巡检子任务过期状态
            patrolSubtaskService.checkAndUpdateExpiredStatus(remotePatrolSubtaskBo.getCycleTaskId(), dateStr);
            return new ArrayList<>();
        }
        // 没有生成，获取主任务信息
        PatrolSubtaskCommon psc = patrolSubtaskService.queryMainTask(remotePatrolSubtaskBo.getTaskId());
        if (Objects.isNull(psc)) {
            return new ArrayList<>();
        }
        psc.setCycleTaskId(remotePatrolSubtaskBo.getCycleTaskId());
        List<PatrolExecutors> patrolExecutorsList = JsonUtils.parseArray(JsonUtils
            .toJsonString(psc.getPatrolExecutors()), PatrolExecutors.class);
        if (CollUtil.isEmpty(patrolExecutorsList) || CollUtil.isEmpty(patrolExecutorsList.get(0).getExecutors())) {
            return null;
        }

        // 检测当前的门店是否存在，如果不存在，那么不在创建任务
        List<Long> storeIds = patrolExecutorsList.stream().map(PatrolExecutors::getStoreId).distinct()
            .filter(ObjUtil::isNotNull)
            .toList();
        Map<Long, Boolean> storeMap = remoteStoreService.queryIsStore(storeIds);
        patrolExecutorsList.removeIf(p -> !storeMap.get(p.getStoreId()));

        // 通过主任务信息，按照循环类型生成每个人、每个门店巡检子任务信息
        List<PatrolSubtaskCommon> list;
        PatrolSubtaskCommon newPsc = getPatrolSubtaskCommon(psc, remotePatrolSubtaskBo);
        // 根据循环类型判断过期状态 NO_REPEAT 不重复，DAILY 每天
        if (RepeatType.NO_REPEAT.getCode().equals(psc.getCycleType())
            || RepeatType.DAILY.getCode().equals(psc.getCycleType())){
            newPsc.setExecuteDateStart(RepeatType.NO_REPEAT.getCode().equals(psc.getCycleType())
                ? psc.getExecuteRule().getExecuteDateStart() : dateStr);
            newPsc.setExecuteDateEnd(RepeatType.NO_REPEAT.getCode().equals(psc.getCycleType())
                ? psc.getExecuteRule().getExecuteDateEnd() : dateStr);
            newPsc.setExecuteTimeStart(psc.getExecuteRule().getExecuteTimeStart());
            newPsc.setExecuteTimeEnd(psc.getExecuteRule().getExecuteTimeEnd());
            newPsc.setExecuteStartTime(DateUtils.parseDate(psc.getExecuteDateStart()
                + " " + psc.getExecuteTimeStart()).getTime());
            Long endTime = DateUtils.parseDate(psc.getExecuteDateEnd()
                +  " " + psc.getExecuteTimeEnd()).getTime();
            newPsc.setExecuteEndTime(endTime);
            newPsc.setExpiredStatus(DateUtils.getTaskExpiredStatusByTime(remotePatrolSubtaskBo.getCurrentTime(),
                psc.getExecuteEndTime(), 1000 * 60 * 60 * 24L));
            newPsc.setStatus(TaskFinishStatus.TODO.getCode());
            list = Lists.newArrayListWithCapacity(patrolExecutorsList.size()
                * patrolExecutorsList.get(0).getExecutors().size());
            patrolExecutorsList.forEach(patrolExecutors -> patrolExecutors.getExecutors().forEach(executors -> {
                PatrolSubtaskCommon temp = BeanUtil.copyProperties(newPsc, PatrolSubtaskCommon.class);
                temp.setStoreId(patrolExecutors.getStoreId());
                temp.setUserId(executors.getExecutor());
                temp.setExecutor(executors.getExecutor());
                list.add(temp);
            }));
        } else if (RepeatType.WEEKLY.getCode().equals(psc.getCycleType())) {
            // WEEKLY 每周
            int week = DateUtil.thisDayOfWeek();
            list = Lists.newArrayListWithCapacity(psc.getExecuteRule().getWeeklyRule().size()
                * patrolExecutorsList.size() * patrolExecutorsList.get(0).getExecutors().size());
            psc.getExecuteRule().getWeeklyRule().forEach(weeklyRule -> {
                // 根据周几，获取对应的时间段，设置时间，如果weeklyRule是周日则修正为下个周日
                weeklyRule = weeklyRule == 1 ? 8 : weeklyRule;
                if (weeklyRule < week) {
                    return;
                }
                if (weeklyRule == week) {
                    newPsc.setExpiredStatus(ExpiredStatus.ABOUT_TO_EXPIRE.getCode());
                } else {
                    newPsc.setExpiredStatus(ExpiredStatus.NOT_EXPIRED.getCode());
                }
                String tempDateStr = DateUtils.getLatestDateOffsetWeek(DateUtils.YYYY_MM_DD, weeklyRule);
                newPsc.setExecuteDateStart(tempDateStr);
                newPsc.setExecuteDateEnd(tempDateStr);
                newPsc.setExecuteTimeStart(psc.getExecuteTimeStart());
                newPsc.setExecuteTimeEnd(psc.getExecuteTimeEnd());
                newPsc.setExecuteStartTime(DateUtils.parseDate(newPsc.getExecuteDateStart()
                    +  " " + psc.getExecuteTimeStart()).getTime());
                newPsc.setExecuteEndTime(DateUtils.parseDate(newPsc.getExecuteDateEnd()
                    +  " " + psc.getExecuteTimeEnd()).getTime());
                newPsc.setStatus(TaskFinishStatus.TODO.getCode());
                patrolExecutorsList
                    .forEach(patrolExecutors -> patrolExecutors.getExecutors()
                        .forEach(executors -> {
                            PatrolSubtaskCommon temp = BeanUtil.copyProperties(newPsc, PatrolSubtaskCommon.class);
                            temp.setStoreId(patrolExecutors.getStoreId());
                            temp.setUserId(executors.getExecutor());
                            temp.setExecutor(executors.getExecutor());
                            list.add(temp);
                        }));
            });
        } else {
            // MONTHLY 每月
            list = Lists.newArrayListWithCapacity(psc.getExecuteRule().getMonthlyRule().size()
                * psc.getPatrolExecutors().size()
                * psc.getPatrolExecutors().get(0).getExecutors().size());
            psc.getExecuteRule().getMonthlyRule().forEach(monthlyRule -> {
                // TODO 一个月的天数，获取对应的时间段，设置时间
            });
        }
        if (patrolSubtaskService.saveBatch(list)) {
            sendMessage(list);
            return list.stream().map(patrolSubtaskCommon -> {
                RemotePatrolSubtaskVo remotePatrolSubtaskVo = BeanUtil.copyProperties(patrolSubtaskCommon,
                    RemotePatrolSubtaskVo.class);
                Objects.requireNonNull(remotePatrolSubtaskVo).setEndTimeStr(patrolSubtaskCommon.getExecuteDateEnd()
                    + " " + patrolSubtaskCommon.getExecuteTimeEnd());
                remotePatrolSubtaskVo.setSendId(patrolSubtaskCommon.getCreator());
                remotePatrolSubtaskVo.setRecordId(patrolSubtaskCommon.getExecutor());
                return remotePatrolSubtaskVo;
            }).collect(Collectors.toList());
        }
        return null;
    }

    private void sendMessage(List<PatrolSubtaskCommon> list) {
        List<RemoteMessageBo> handlerMessageList = new ArrayList<>();
        list.forEach(patrolSubtaskCommon -> {
            RemoteMessageBo messageBo = new RemoteMessageBo();
            messageBo.setRecordId(patrolSubtaskCommon.getExecutor());
            messageBo.setStoreId(patrolSubtaskCommon.getStoreId());
            messageBo.setSendId(patrolSubtaskCommon.getCreator());
            handlerMessageList.add(messageBo);
        });
        //根据接收人id,转化成map集合
        Map<Long, List<RemoteMessageBo>> map = handlerMessageList.stream().
            collect(Collectors.groupingBy(RemoteMessageBo::getRecordId));
        handlerMessageList.clear();
        map.forEach((k, v) -> {
            RemoteMessageBo remoteMessageBo = new RemoteMessageBo();
            remoteMessageBo.setType(NoticeMessageType.NOTICE_RECEIVE_TASK);
            remoteMessageBo.setMessageContent( NoticeMessageType.NOTICE_RECEIVE_TASK.getAlert().formatted(v.size()));
            remoteMessageBo.setTitle(NoticeMessageType.NOTICE_RECEIVE_TASK.getTitle());
            remoteMessageBo.setStatus("0");
            remoteMessageBo.setRecordId(k);
            remoteMessageBo.setSendId(v.get(0).getSendId());
            remoteMessageBo.setCreateBy(v.get(0).getSendId());
            remoteMessageBo.setUpdateBy(v.get(0).getSendId());
            remoteMessageBo.setUrl("/inspectionManagement/task/taskList");
            handlerMessageList.add(remoteMessageBo);
        });
        remoteMessageService.insertBatchByBo(handlerMessageList);
    }

    /**
     * 刷新子非主任务过期状态
     * @param id
     * @return
     */
    @Override
    public Boolean updateNonMainPatrolSubtask(Long id) {
        return patrolSubtaskService.queryUnFinishTaskUpdateStatusIsExpired(id);
    }

    /**
     * 更新子主任务过期状态
     * @param id
     * @return
     */
    @Override
    public Boolean updateMainPatrolTask(Long id) {
        return patrolSubtaskService.queryUnFinishTaskUpdateMainStatusIsExpired(id);
    }

    /**
     * 批量更新定时任务id
     * @param vo
     * @return
     */
    @Override
    public Boolean updateCyclicTaskById(List<RemotePatrolSubtaskVo> vo) {
        List<PatrolSubtaskCommon> list = Lists.newArrayListWithCapacity(vo.size());
        vo.forEach(remotePatrolSubtaskVo ->
            list.add(BeanUtil.copyProperties(remotePatrolSubtaskVo, PatrolSubtaskCommon.class)));
        return patrolSubtaskService.updateBatchById(list);
    }

    /**
     * 获取 patrolSubtaskCommon
     * @param psc
     * @param remotePatrolSubtaskBo
     * @return
     */
    private PatrolSubtaskCommon getPatrolSubtaskCommon(PatrolSubtaskCommon psc, RemotePatrolSubtaskBo remotePatrolSubtaskBo) {
        PatrolSubtaskCommon newPsc = BeanUtil.copyProperties(psc, PatrolSubtaskCommon.class);
        newPsc.setId(null);
        newPsc.setCreateBy(null);
        newPsc.setUpdateBy(null);
        newPsc.setTaskCreatedTime(remotePatrolSubtaskBo.getCurrentTime());
        newPsc.setCreateTime(new Date(remotePatrolSubtaskBo.getCurrentTime()));
        newPsc.setUpdateTime(new Date(remotePatrolSubtaskBo.getCurrentTime()));
        newPsc.setMainTask(MainTaskType.NON_MAIN.getCode());
        newPsc.setStoreIds(null);
        newPsc.setPatrolExecutors(null);
        return newPsc;
    }

    /**
     * 通过任务IDS，获取任务名称
     * @param ids
     * @return
     */
    @Override
    public Map<Long, String> getPatrolTaskNameMap(List<Long> ids) {
        List<Long> filterIds = ids.stream().filter(Objects::nonNull).toList();
        if (CollUtil.isEmpty(filterIds)) {
            return Maps.newHashMap();
        }
        return patrolSubtaskService.queryList(filterIds)
            .stream()
            .filter(Objects::nonNull)
            .collect(Collectors
                .toMap(PatrolSubtaskCommon::getId, PatrolSubtaskCommon::getName));
    }

    /**
     * 通过任务ID，获取任务信息，包括关联ID的名称
     * @param id
     * @return
     */
    @Override
    public RemotePatrolTaskVo getPatrolTaskInfoList(Long id) {
        PatrolSubtaskCommonVo vo = patrolSubtaskService.queryById(id);
        RemotePatrolTaskVo remotePatrolTaskVo = BeanUtil.copyProperties(vo, RemotePatrolTaskVo.class);
        return remotePatrolTaskVo;
    }

    /**
     * 删除门店关联的巡店任务，包含独立主任务和子任务
     * @param storeId
     * @return
     */
    @Override
    public Boolean deleteStoreLinkageHandleTask(Long storeId) {
        return patrolSubtaskService.deleteTaskWithStoreId(storeId);
    }
}
